package com.example.ipcclient.client;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.example.hand_write_ipc.BookListener;
import com.example.hand_write_ipc.BookManager;
import com.example.hand_write_ipc.IBookListener;
import com.example.hand_write_ipc.IBookManager;
import com.example.ipc.Book;
import com.example.ipc.IBookByAidl;
import com.example.ipcclient.R;

import java.util.List;

import static com.example.ipcclient.constants.Constants.MSG;
import static com.example.ipcclient.constants.Constants.TAG;


public class ClientActivity extends Activity {
    TextView send;
    TextView addBook;
    TextView addBookBinder;

    Messenger mServiceMessenger;
    Messenger mClientMessenger;

    IBookByAidl mBookByAidl;

    IBookManager mBookManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        send = findViewById(R.id.send);
        addBook = findViewById(R.id.add_book);
        addBookBinder = findViewById(R.id.add_book_binder);

        send.setOnClickListener(mOnClickListener);
        addBook.setOnClickListener(mOnClickListener);
        addBookBinder.setOnClickListener(mOnClickListener);

        Intent intent = new Intent("com.example.ipc.MessengerServer");
        Intent explicit = createExplicitFromImplicitIntent(this, intent);
        bindService(explicit, mMessengerConnection, BIND_AUTO_CREATE);

        intent = new Intent("com.example.ipc.AidlServer");
        explicit = createExplicitFromImplicitIntent(this, intent);
        bindService(explicit, mAidlConnection, BIND_AUTO_CREATE);

        intent = new Intent("com.example.ipc.BinderServer");
        explicit = createExplicitFromImplicitIntent(this, intent);
        bindService(explicit, mBinderConnection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mMessengerConnection);
        unbindService(mAidlConnection);
        unbindService(mBinderConnection);
    }

    private Intent createExplicitFromImplicitIntent(Context context, Intent intent) {
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent, 0);
        if (resolveInfos.size() <= 0) {
            return null;
        }
        ResolveInfo resolveInfo = resolveInfos.get(0);
        Intent resultIntent = new Intent();
        resultIntent.setComponent(new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name));
        return resultIntent;
    }

    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.send:
                    sendMessage();
                    break;
                case R.id.add_book:
                    addBook();
                    break;
                case R.id.add_book_binder:
                    addBookBinder();
                    break;
            }
        }
    };

    private void sendMessage() {
        if (mServiceMessenger != null) {
            try {
                Bundle bundle = new Bundle();
                bundle.putString(MSG, "Hello server, i am client app");
                bundle.putParcelable("book", new Book("Android，从入门到放弃"));

                Message msg = new Message();
                msg.setData(bundle);
                msg.replyTo = mClientMessenger;

                mServiceMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(ClientActivity.this, "Messenger not ready yet", Toast.LENGTH_SHORT).show();
        }
    }

    private static class MessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            String fromServer = (String) msg.getData().get(MSG);
            Log.i(TAG, "got msg: " + fromServer);
        }
    }

    private ServiceConnection mMessengerConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mServiceMessenger = new Messenger(service);
            mClientMessenger = new Messenger(new MessageHandler());
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private ServiceConnection mAidlConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBookByAidl = IBookByAidl.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private ServiceConnection mBinderConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBookManager = BookManager.asInterface(service);
            try {
                mBookManager.addBookListener(mBookListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private void addBook() {
        if (mBookByAidl != null) {
            try {
                String name = "Book with id: " + (int) (Math.random() * 1000);
                mBookByAidl.addBook(new Book(name));
                List<Book> books = mBookByAidl.getBooks();
                Log.i(TAG, "currentBook is ------------------------------------------------------ ");
                for (int i = 0; i < books.size(); i++) {
                    Log.i(TAG, "Book index: " + i + " : " + books.get(i));
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "Book aidl not ready yet", Toast.LENGTH_SHORT).show();
        }
    }

    private void addBookBinder() {
        if (mBookManager != null) {
            try {
                String name = "Book with id: " + (int) (Math.random() * 1000);
                mBookManager.addBook(new Book(name));
                List<Book> books = mBookManager.getBookList();
                Log.i(TAG, "currentBook is ------------------------------------------------------ ");
                for (int i = 0; i < books.size(); i++) {
                    Log.i(TAG, "Book index: " + i + " : " + books.get(i));
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "Book manager not ready yet", Toast.LENGTH_SHORT).show();
        }
    }

    private IBookListener mBookListener = new BookListener() {
        @Override
        public void onNewBookArrival(Book book) throws RemoteException {
            List<Book> books = mBookManager.getBookList();
            Log.i(TAG, "onNewBookArrival,currentBook is ------------------------------------------------------ ");
            for (int i = 0; i < books.size(); i++) {
                Log.i(TAG, "Book index: " + i + " : " + books.get(i));
            }

        }
    };
}
